using System.Net.NetworkInformation;
using System.Diagnostics;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Runtime.InteropServices;
using Toolbox.DnsService.Models;

namespace Toolbox.Common
{
    /// <summary>
    /// DNS工具类
    /// 作者：huobing
    /// </summary>
    public static class DnsUtilities
    {
        /// <summary>
        /// 测试DNS服务器响应时间
        /// </summary>
        /// <param name="dnsServer">DNS服务器IP地址</param>
        /// <param name="timeout">超时时间（毫秒）</param>
        /// <returns>响应时间（毫秒），如果测试失败返回-1</returns>
        public static async Task<int> TestDnsResponseTimeAsync(string dnsServer, int timeout = 5000)
        {
            try
            {
                using Ping ping = new();
                PingReply reply = await ping.SendPingAsync(dnsServer, timeout);

                return reply.Status == IPStatus.Success ? (int)reply.RoundtripTime : -1;
            }
            catch
            {
                return -1;
            }
        }

        /// <summary>
        /// 应用DNS设置
        /// </summary>
        /// <param name="dnsServer">DNS服务器IP地址</param>
        /// <param name="interfaceName">网络接口名称，默认为"本地连接"</param>
        /// <returns>操作结果消息</returns>
        public static async Task<string> ApplyDnsSettingsAsync(string dnsServer, string interfaceName = "本地连接")
        {
            try
            {
                // 构建netsh命令
                string command = $"netsh interface ip set dns name=\"{interfaceName}\" source=static addr={dnsServer}";

                // 执行命令
                ProcessStartInfo startInfo = new()
                {
                    FileName = "cmd.exe",
                    Arguments = $"/c {command}",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true,
                    Verb = "runas" // 请求管理员权限
                };

                using Process? process = Process.Start(startInfo);
                if (process != null)
                {
                    string output = process.StandardOutput?.ReadToEnd() ?? string.Empty;
                    string error = process.StandardError?.ReadToEnd() ?? string.Empty;
                    await process.WaitForExitAsync();

                    return process.ExitCode == 0 ? $"DNS设置已成功应用：{dnsServer}" : $"DNS设置应用失败：{error}";
                }

                return "无法启动进程";
            }
            catch (Exception ex)
            {
                return $"应用DNS设置时发生错误: {ex.Message}";
            }
        }

        /// <summary>
        /// 刷新DNS缓存
        /// </summary>
        /// <returns>操作结果消息</returns>
        public static async Task<string> FlushDnsCacheAsync()
        {
            try
            {
                ProcessStartInfo startInfo = new()
                {
                    FileName = "ipconfig",
                    Arguments = "/flushdns",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                };

                using Process process = new() { StartInfo = startInfo };
                _ = process.Start();
                string output = await process.StandardOutput.ReadToEndAsync();
                string error = await process.StandardError.ReadToEndAsync();
                await process.WaitForExitAsync();

                return process.ExitCode == 0 ? $"DNS缓存刷新结果：\r\n{output}" : $"刷新DNS缓存失败：{error}";
            }
            catch (Exception ex)
            {
                return $"刷新DNS缓存时发生错误: {ex.Message}";
            }
        }

        /// <summary>
        /// 测试域名解析
        /// </summary>
        /// <param name="domain">要测试的域名</param>
        /// <param name="dnsServer">DNS服务器IP地址</param>
        /// <param name="timeout">超时时间（秒）</param>
        /// <returns>测试结果</returns>
        public static async Task<DnsTestResult> TestDomainResolutionAsync(string domain, string dnsServer, int timeout = 5)
        {
            DnsTestResult result = new()
            {
                IsSuccess = false,
                ResponseTimeMs = 0,
                ResolvedIp = null,
                ErrorMessage = null,
                TestTime = DateTime.Now
            };

            try
            {
                Stopwatch stopwatch = Stopwatch.StartNew();
                
                // 使用DnsClient库或自定义DNS查询逻辑
                // 这里简化实现，实际项目中可能需要使用专门的DNS库
                IPHostEntry hostEntry = await Dns.GetHostEntryAsync(domain);
                
                stopwatch.Stop();
                
                if (hostEntry.AddressList.Length > 0)
                {
                    result.ResolvedIp = hostEntry.AddressList[0]?.ToString() ?? string.Empty;
                    result.IsSuccess = true;
                    result.ResponseTimeMs = stopwatch.ElapsedMilliseconds;
                }
                else
                {
                    result.ErrorMessage = "未找到IP地址";
                    result.IsSuccess = false;
                    result.ResponseTimeMs = stopwatch.ElapsedMilliseconds;
                }
            }
            catch (Exception ex)
            {
                result.ErrorMessage = ex.Message;
                result.IsSuccess = false;
            }

            return result;
        }

        /// <summary>
        /// 获取当前DNS信息
        /// </summary>
        /// <returns>当前DNS信息字符串</returns>
        public static string GetCurrentDnsInfo()
        {
            try
            {
                IEnumerable<NetworkInterface> networkInterfaces = NetworkInterface.GetAllNetworkInterfaces()
                    .Where(static ni => ni.OperationalStatus == OperationalStatus.Up &&
                                ni.NetworkInterfaceType != NetworkInterfaceType.Loopback);

                foreach (NetworkInterface? ni in networkInterfaces)
                {
                    IPInterfaceProperties properties = ni.GetIPProperties();
                    IPAddressCollection dnsAddresses = properties.DnsAddresses;

                    if (dnsAddresses.Count > 0)
                    {
                        return $"当前DNS服务器: {string.Join(", ", dnsAddresses.Select(static ip => ip.ToString()))}";
                    }
                }
            }
            catch (Exception ex)
            {
                return $"获取DNS信息失败: {ex.Message}";
            }

            return "未检测到DNS服务器设置";
        }

        /// <summary>
        /// 获取占用指定端口的进程信息
        /// </summary>
        /// <param name="port">端口号</param>
        /// <returns>进程信息字符串</returns>
        public static string GetPortProcessInfo(int port)
        {
            try
            {
                ProcessStartInfo startInfo = new()
                {
                    FileName = "netstat",
                    Arguments = $"-ano | findstr :{port}",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    CreateNoWindow = true
                };

                using Process process = new() { StartInfo = startInfo };
                _ = process.Start();
                string output = process.StandardOutput.ReadToEnd();
                process.WaitForExit();

                if (!string.IsNullOrEmpty(output))
                {
                    string[] lines = output.Split('\n', StringSplitOptions.RemoveEmptyEntries);
                    StringBuilder result = new();

                    foreach (string line in lines)
                    {
                        if (line.Contains($":{port}") && !line.Trim().EndsWith("TIME_WAIT"))
                        {
                            string[] parts = line.Split([' '], StringSplitOptions.RemoveEmptyEntries);
                            if (parts.Length >= 5)
                            {
                                string protocol = parts[0];
                                string localAddress = parts[1];
                                string remoteAddress = parts[2];
                                string state = parts[3];
                                string processId = parts[4];

                                _ = result.AppendLine($"协议: {protocol}, 本地地址: {localAddress}, 远程地址: {remoteAddress}, 状态: {state}, 进程ID: {processId}");

                                try
                                {
                                    Process proc = Process.GetProcessById(int.Parse(processId));
                                    _ = result.AppendLine($"进程名称: {proc.ProcessName}, 路径: {proc.MainModule?.FileName ?? "未知"}");
                                }
                                catch
                                {
                                    _ = result.AppendLine("无法获取进程详细信息");
                                }

                                _ = result.AppendLine();
                            }
                        }
                    }

                    return result.Length > 0 ? result.ToString() : $"端口 {port} 未被占用或仅处于TIME_WAIT状态";
                }
                else
                {
                    return $"端口 {port} 未被占用";
                }
            }
            catch (Exception ex)
            {
                return $"获取端口 {port} 占用信息时发生错误: {ex.Message}";
            }
        }

        /// <summary>
        /// 检查端口是否被占用
        /// </summary>
        /// <param name="port">端口号</param>
        /// <returns>如果端口被占用返回true，否则返回false</returns>
        public static bool IsPortInUse(int port)
        {
            try
            {
                using UdpClient testClient = new(port);
                // 端口可用
                return false;
            }
            catch (SocketException)
            {
                // 端口被占用
                return true;
            }
        }

        // 以下是Model.DNSService.DnsUtilities中的方法

        /// <summary>
        /// 获取当前系统DNS服务器
        /// </summary>
        /// <returns>DNS服务器列表</returns>
        public static List<string> GetCurrentDnsServers()
        {
            List<string> dnsServers = [];

            try
            {
                NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
                foreach (NetworkInterface adapter in adapters)
                {
                    if (adapter.OperationalStatus == OperationalStatus.Up &&
                        adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback)
                    {
                        IPInterfaceProperties adapterProperties = adapter.GetIPProperties();
                        IPAddressCollection dnsAddresses = adapterProperties.DnsAddresses;

                        foreach (IPAddress dns in dnsAddresses)
                        {
                            string dnsAddress = dns.ToString();
                            if (!dnsServers.Contains(dnsAddress))
                            {
                                dnsServers.Add(dnsAddress);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"获取DNS服务器失败: {ex.Message}");
            }

            return dnsServers;
        }

        /// <summary>
        /// 设置系统DNS服务器
        /// </summary>
        /// <param name="dnsServers">DNS服务器列表</param>
        /// <returns>设置是否成功</returns>
        public static bool SetDnsServers(List<string> dnsServers)
        {
            try
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    return SetWindowsDnsServers(dnsServers);
                }
                else
                {
                    // 其他平台的实现
                    return false;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"设置DNS服务器失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 刷新DNS缓存
        /// </summary>
        /// <returns>刷新是否成功</returns>
        public static bool FlushDnsCache()
        {
            try
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    ProcessStartInfo startInfo = new()
                    {
                        FileName = "ipconfig",
                        Arguments = "/flushdns",
                        UseShellExecute = false,
                        CreateNoWindow = true,
                        RedirectStandardOutput = true,
                        RedirectStandardError = true
                    };

                    using Process? process = Process.Start(startInfo);
                    if (process != null)
                    {
                        process.WaitForExit();
                        return process.ExitCode == 0;
                    }
                }
                else
                {
                    // 其他平台的实现
                    return false;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"刷新DNS缓存失败: {ex.Message}");
                return false;
            }

            return false;
        }

        /// <summary>
        /// 测试DNS解析
        /// </summary>
        /// <param name="domain">要测试的域名</param>
        /// <param name="dnsServer">DNS服务器地址</param>
        /// <param name="timeout">超时时间（毫秒）</param>
        /// <returns>测试结果</returns>
        public static DnsTestResult TestDnsResolution(string domain, string dnsServer, int timeout = 5000)
        {
            DnsTestResult result = new()
            {
                IsSuccess = false,
                ResponseTimeMs = 0,
                ResolvedIp = null,
                ErrorMessage = null,
                TestTime = DateTime.Now
            };

            try
            {
                // 解析DNS服务器地址和端口
                string[] serverParts = dnsServer.Split(':');
                string serverIp = serverParts[0];
                int serverPort = serverParts.Length > 1 ? int.Parse(serverParts[1]) : 53;

                Stopwatch stopwatch = Stopwatch.StartNew();

                // 使用指定的DNS服务器进行解析
                using UdpClient udpClient = new();
                udpClient.Client.ReceiveTimeout = timeout;

                // 创建DNS查询
                byte[] queryData = CreateDnsQuery(domain);

                // 发送查询到指定的DNS服务器
                IPEndPoint serverEndPoint = new(IPAddress.Parse(serverIp), serverPort);
                _ = udpClient.Send(queryData, queryData.Length, serverEndPoint);

                // 接收响应
                UdpReceiveResult receiveResult = udpClient.ReceiveAsync().Result;
                byte[] response_data = receiveResult.Buffer;

                // 解析响应获取IP地址
                string resolvedIp = ExtractIpFromDnsResponse(response_data);

                stopwatch.Stop();

                result.ResponseTimeMs = stopwatch.ElapsedMilliseconds;
                result.IsSuccess = true;
                result.ResolvedIp = resolvedIp;
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.ErrorMessage = ex.Message;
            }

            return result;
        }

        /// <summary>
        /// 创建DNS查询
        /// </summary>
        /// <param name="domain">域名</param>
        /// <returns>DNS查询数据</returns>
        private static byte[] CreateDnsQuery(string domain)
        {
            using MemoryStream stream = new();
            using BinaryWriter writer = new(stream);

            // DNS头部
            writer.Write((ushort)Random.Shared.Next(0, 65536)); // 事务ID
            writer.Write((ushort)0x0100); // 标志：标准查询
            writer.Write((ushort)1); // 问题数
            writer.Write((ushort)0); // 回答数
            writer.Write((ushort)0); // 权威记录数
            writer.Write((ushort)0); // 附加记录数

            // 查询部分
            string[] parts = domain.Split('.');
            foreach (string part in parts)
            {
                writer.Write((byte)part.Length);
                writer.Write(Encoding.ASCII.GetBytes(part));
            }
            writer.Write((byte)0); // 结束标签

            writer.Write((ushort)1); // 查询类型：A记录
            writer.Write((ushort)1); // 查询类：IN

            return stream.ToArray();
        }

        /// <summary>
        /// 从DNS响应中提取IP地址
        /// </summary>
        /// <param name="responseData">DNS响应数据</param>
        /// <returns>IP地址</returns>
        private static string ExtractIpFromDnsResponse(byte[] responseData)
        {
            if (responseData == null || responseData.Length < 12)
            {
                return string.Empty;
            }

            try
            {
                // 跳过DNS头部（12字节）
                int offset = 12;

                // 跳过查询部分
                while (offset < responseData.Length && responseData[offset] != 0)
                {
                    int length = responseData[offset];
                    offset += length + 1;
                }
                offset += 5; // 跳过结束标签和查询类型/类

                // 检查回答部分
                if (offset + 10 < responseData.Length)
                {
                    // 跳过回答部分的前10字节（名称指针、类型、类、TTL）
                    offset += 10;

                    // 读取数据长度
                    int dataLength = responseData[offset] << 8 | responseData[offset + 1];
                    offset += 2;

                    // 检查是否为A记录（4字节IP地址）
                    if (dataLength == 4 && offset + 4 <= responseData.Length)
                    {
                        byte[] ipBytes = new byte[4];
                        Array.Copy(responseData, offset, ipBytes, 0, 4);
                        return new IPAddress(ipBytes).ToString();
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"解析DNS响应失败: {ex.Message}");
            }

            return string.Empty;
        }

        /// <summary>
        /// Windows平台设置DNS服务器
        /// </summary>
        /// <param name="dnsServers">DNS服务器列表</param>
        /// <returns>设置是否成功</returns>
        private static bool SetWindowsDnsServers(List<string> dnsServers)
        {
            try
            {
                // 获取所有活动的网络适配器
                NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
                foreach (NetworkInterface adapter in adapters)
                {
                    if (adapter.OperationalStatus == OperationalStatus.Up &&
                        adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback)
                    {
                        // 跳过VPN等特殊适配器
                        if (adapter.Description.Contains("Virtual") ||
                            adapter.Description.Contains("VPN") ||
                            adapter.Description.Contains("Tunnel"))
                        {
                            continue;
                        }

                        // 构建netsh命令
                        StringBuilder args = new("interface ip set dns \"");
                        _ = args.Append(adapter.Name);
                        _ = args.Append("\" static ");

                        if (dnsServers.Count > 0)
                        {
                            _ = args.Append(dnsServers[0]);
                        }

                        ProcessStartInfo startInfo = new()
                        {
                            FileName = "netsh",
                            Arguments = args.ToString(),
                            UseShellExecute = false,
                            CreateNoWindow = true,
                            RedirectStandardOutput = true,
                            RedirectStandardError = true
                        };

                        using Process? process = Process.Start(startInfo);
                        if (process != null)
                        {
                            process.WaitForExit();
                            if (process.ExitCode != 0)
                            {
                                return false;
                            }
                        }

                        // 设置备用DNS服务器
                        for (int i = 1; i < dnsServers.Count; i++)
                        {
                            _ = args.Clear();
                            _ = args.Append("interface ip add dns \"");
                            _ = args.Append(adapter.Name);
                            _ = args.Append("\" ");
                            _ = args.Append(dnsServers[i]);
                            _ = args.Append(" index=");
                            _ = args.Append(i + 1);

                            startInfo.Arguments = args.ToString();

                            using Process? addProcess = Process.Start(startInfo);
                            if (addProcess != null)
                            {
                                addProcess.WaitForExit();
                                if (addProcess.ExitCode != 0)
                                {
                                    return false;
                                }
                            }
                        }
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"设置Windows DNS服务器失败: {ex.Message}");
                return false;
            }
        }
    }


}